/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.openmrs.module.basicmodule.DSS.XMLApp;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import org.openmrs.module.basicmodule.DSS.ast.AST;
import org.openmrs.module.basicmodule.DSS.ast.IdTree;
import org.openmrs.module.basicmodule.DSS.ast.LiteralTree;
import org.openmrs.module.basicmodule.DSS.ast.OpTree;
import org.openmrs.module.basicmodule.DSS.visitor.ASTVisitor;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;


/**
 *
 * @author bhavana
 */
public class XMLGenerator extends ASTVisitor{

  File f;
  FileWriter fw;
  BufferedWriter bw;
  StreamResult result;
  
  TransformerFactory tf;
  SAXTransformerFactory stf;
  TransformerHandler th;
  Transformer transformer;
  
  String finalFilePath;
  String XMLOutputFileName;
  String workingDir;

  public XMLGenerator(String filename) throws TransformerConfigurationException, IOException{
        finalFilePath = "";
        XMLOutputFileName = filename;
        workingDir = System.getProperty("user.dir");
        System.out.print(workingDir);
        finalFilePath = workingDir + File.separator + XMLOutputFileName;
        System.out.print(finalFilePath); 
        f = new File(finalFilePath);
        fw = new FileWriter(f);
        bw = new BufferedWriter(fw);
        result = new StreamResult(bw);
        
        tf = TransformerFactory.newInstance();
        stf = (SAXTransformerFactory)tf;
        th = stf.newTransformerHandler();
        transformer = th.getTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT,"yes");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
        th.setResult(result);
  
  }
  
  
  @Override
  public Object visitProgramTree(AST t) {
    try {
        th.startDocument();
          AttributesImpl fieldAttrs = new AttributesImpl();
          fieldAttrs.addAttribute("", "", "", "", "");
          th.startElement("", "", "Program", null);
          visitKids(t);
          th.endElement("", "", "Program");
        th.endDocument();
      } catch (SAXException ex) {
      Logger.getLogger(XMLGenerator.class.getName()).log(Level.SEVERE, null, ex);
    } 
    return null;
  }

  @Override
  public Object visitBlockTree(AST t) {
    try {
      th.startElement("", "", "Block", null);
      visitKids(t);
      th.endElement("", "", "Block");
    } catch (SAXException ex) {
      Logger.getLogger(XMLGenerator.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
  }

  @Override
  public Object visitFunctionDeclTree(AST t) {
    try {
      th.startElement("", "", "FunctionDecl", null);
      visitKids(t);
      th.endElement("", "", "FunctionDecl");
    } catch (SAXException ex) {
      Logger.getLogger(XMLGenerator.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;  
  }

  @Override
  public Object visitObjectDeclTree(AST t) {
    try {
      th.startElement("", "", "ObjectDecl", null);
      visitKids(t);
      th.endElement("", "", "ObjectDecl");
    } catch (SAXException ex) {
      Logger.getLogger(XMLGenerator.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
  }

  @Override
  public Object visitCallTree(AST t) {
    try {
      th.startElement("", "", "Call", null);
      visitKids(t);
      th.endElement("", "", "Call");
    } catch (SAXException ex) {
      Logger.getLogger(XMLGenerator.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
  }

  @Override
  public Object visitFormalsTree(AST t) {
    try {
      th.startElement("", "", "FormalsTree", null);
      visitKids(t);
      th.endElement("", "", "FormalsTree");
    } catch (SAXException ex) {
      Logger.getLogger(XMLGenerator.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;  
  }

  @Override
  public Object visitIfTree(AST t) {
    try {
      th.startElement("", "", "If", null);
      System.out.println('\n');
      visitKids(t);
      th.endElement("", "", "If");
    } catch (SAXException ex) {
      Logger.getLogger(XMLGenerator.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;    
  }

  @Override
  public Object visitWhileTree(AST t) {
    try {
      th.startElement("", "", "While", null);
      visitKids(t);
      th.endElement("", "", "While");
    } catch (SAXException ex) {
      Logger.getLogger(XMLGenerator.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;      
  }

  @Override
  public Object visitForTree(AST t) {
    try {
      th.startElement("", "", "For", null);
      visitKids(t);
      th.endElement("", "", "For");
    } catch (SAXException ex) {
      Logger.getLogger(XMLGenerator.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
  }

  @Override
  public Object visitReturnTree(AST t) {
    try {
      th.startElement("", "", "Return", null);
      visitKids(t);
      th.endElement("", "", "Return");
    } catch (SAXException ex) {
      Logger.getLogger(XMLGenerator.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
  }

  @Override
  public Object visitAssignTree(AST t) {
    try {
      th.startElement("", "", "Assign", null);
      visitKids(t);
      th.endElement("", "", "Assign");
    } catch (SAXException ex) {
      Logger.getLogger(XMLGenerator.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
  }

  @Override
  public Object visitLiteralTree(AST t) {
    try {
      AttributesImpl fieldAttrs = new AttributesImpl();
      fieldAttrs.addAttribute("", "", "Value", "", ((LiteralTree) t).getSymbol().toString());
      th.startElement("", "", "Literal", fieldAttrs);
      visitKids(t);
      th.endElement("", "", "Literal");
    } catch (SAXException ex) {
      Logger.getLogger(XMLGenerator.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
  }

  @Override
  public Object visitIdTree(AST t) {
    try {
      AttributesImpl fieldAttrs = new AttributesImpl();
      fieldAttrs.addAttribute("", "", "Label", "", ((IdTree) t).getSymbol().toString());
      th.startElement("", "", "Id", fieldAttrs);
      visitKids(t);
      th.endElement("", "", "Id");
    } catch (SAXException ex) {
      Logger.getLogger(XMLGenerator.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
  }

  @Override
  public Object visitObjectTree(AST t) {
    try {
      th.startElement("", "", "Object", null);
      visitKids(t);
      th.endElement("", "", "Object");
    } catch (SAXException ex) {
      Logger.getLogger(XMLGenerator.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
  }

  @Override
  public Object visitOpTree(AST t) {
    try {
      AttributesImpl fieldAttrs = new AttributesImpl();
      fieldAttrs.addAttribute("", "", "Operator", "", ((OpTree) t).getSymbol().toString());
      th.startElement("", "", "Op", fieldAttrs);
      visitKids(t);
      th.endElement("", "", "Op");
    } catch (SAXException ex) {
      Logger.getLogger(XMLGenerator.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
  }

  @Override
  public Object visitFieldRefTree(AST t) {
    try {
      th.startElement("", "", "FieldRef", null);
      visitKids(t);
      th.endElement("", "", "FieldRef");
    } catch (SAXException ex) {
      Logger.getLogger(XMLGenerator.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
  }

  @Override
  public Object visitListTree(AST t) {
    try {
      th.startElement("", "", "ListTree", null);
      visitKids(t);
      th.endElement("", "", "ListTree");
    } catch (SAXException ex) {
      Logger.getLogger(XMLGenerator.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
  }

  @Override
  public Object visitElsifTree(AST t) {
    try {
      th.startElement("", "", "ElseifTree", null);
      visitKids(t);
      th.endElement("", "", "ElseifTree");
    } catch (SAXException ex) {
      Logger.getLogger(XMLGenerator.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
  }
  
//  public Object visitActualArgsTree(AST t) {
//    try {
//      th.startElement("", "", "ActualArgs", null);
//      visitKids(t);
//      th.endElement("", "", "ActualArgs");
//    } catch (SAXException ex) {
//      Logger.getLogger(XMLGenerator.class.getName()).log(Level.SEVERE, null, ex);
//    }
//    return null;  
//  }
}